
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import matrice.ConstantesTetris;
import musique.CheminMusique;
import sprites.CheminSprites;
import sprites.GestionSpritesTetriminos;
import sprites.PositionsSprites;



@SuppressWarnings("serial")
public class TetrisApplet extends Applet implements Runnable, CheminSprites, PositionsSprites, ConstantesTetris, CheminMusique
{
	private static final int w=800;
	private static final int h=600;						//r�solution de l'applet
	static final int REFRESH_RATE = 50;					//taux de rafraichissement de l'image en ms
	private Graphics buffer;							//buffer �vitant le clipping
	private Image image;								//image permettant
	private Thread animation;							//thread utilis� pour l'animation
	private List<Image> sprites;						//liste des images utilis� pour les tetriminos
	private Map<String,AudioClip> musics;
	private Image fond;									//image du d�cors
	private Image pauseImg;
	private Image gameOver;
	private boolean jeu;			
	private boolean pause;	
	private long chrono;								//variable permettant de diff�rencier l'attente pour la chute et la vitesse de rafraichissement de l'�cran
	private Gestion gestion;							//variable permettant les modification sur le model	
	private GestionSpritesTetriminos gestionSprites;	//variable permettant de faire les modifications sur la vue
	
	/**initialise les variables de l'applet et ajoute l'�couteur sur le clavier*/
	public void init() 
	{ 
		
        this.addKeyListener(new EvenementClavier());
        
		this.chrono=0;
		
		jeu=false;
		pause=false;
		
		sprites=new ArrayList<Image>();
		sprites.add(getImage(getCodeBase(), GRIS_CLASSIQUE));
		sprites.add(getImage(getCodeBase(), JAUNE_CLASSIQUE));
		sprites.add(getImage(getCodeBase(), BLEU_CLAIR_CLASSIQUE));
		sprites.add(getImage(getCodeBase(), ROUGE_CLASSIQUE ));
		sprites.add(getImage(getCodeBase(), VERT_CLASSIQUE ));
		sprites.add(getImage(getCodeBase(), BLEU_FONCE_CLASSIQUE ));
		sprites.add(getImage(getCodeBase(), ORANGE_CLASSIQUE ));
		sprites.add(getImage(getCodeBase(), VIOLET_CLASSIQUE));
		fond = getImage(getCodeBase(),FOND_SKY);
		pauseImg = getImage(getCodeBase(),PAUSE);
		gameOver = getImage(getCodeBase(),GAME_OVER);
		
		MediaTracker tracker = new MediaTracker(this);
		for (int i = 0; i < sprites.size(); i++) {
			tracker.addImage(sprites.get(i), SPRITES_TETRIMINOS);
		}
		tracker.addImage(fond, FOND_D_ECRAN);
		tracker.addImage(pauseImg, FOND_D_ECRAN);
		tracker.addImage(gameOver, FOND_D_ECRAN);
	  
	    try 
	    {
	    	tracker.waitForID(FOND_D_ECRAN);
	    	tracker.waitForID(SPRITES_TETRIMINOS);
	    }
        catch(InterruptedException e) 
        	{return;}
        gestionSprites= new GestionSpritesTetriminos(sprites, fond, gameOver, pauseImg);
		
		musics = new HashMap<String,AudioClip>();
		musics.put("uneLigne",getAudioClip(getCodeBase(),UNELIGNE));
		musics.put("deuxLignes",getAudioClip(getCodeBase(),DEUXLIGNES));
		musics.put("troisLignes",getAudioClip(getCodeBase(),TROISLIGNES));
		musics.put("quatreLignes",getAudioClip(getCodeBase(),QUATRESLIGNES));
		musics.put("choixMenu",getAudioClip(getCodeBase(),CHXMENU));
		musics.put("bgm",getAudioClip(getCodeBase(),MUSIQUE));
		musics.put("palier",getAudioClip(getCodeBase(),PALIER));
		musics.put("tetriminoAtteris",getAudioClip(getCodeBase(),PIECEATTERIS));
		musics.put("retourArriere",getAudioClip(getCodeBase(),RETOURENARRIERE));
		musics.put("perdu",getAudioClip(getCodeBase(),PERDU));
		musics.put("aDroite",getAudioClip(getCodeBase(),ADROITE));
		musics.put("aGauche",getAudioClip(getCodeBase(),AGAUCHE));
		musics.put("tourner",getAudioClip(getCodeBase(),TOURNER));
        gestion=new Gestion(musics);
        
        setBackground(Color.BLACK);
        requestFocus();
	}
	
	/**cr�ation du thread d'animation*/
	public void start() 
	{
		animation = new Thread(this);
		if (animation != null) 
		{ 
			animation.start();
		}
	}
	
	/**cr�er l'imge dans le buffer et repaint l'�cran*/
	public void paint(Graphics g) 
	{  
		if(image==null)
		{
			image = createImage(w,h);
			buffer = image.getGraphics();
		}
		
		gestionSprites.paint(buffer);
		buffer.drawString(gestion.getScore(), 20, 54);
		buffer.drawString(gestion.getMeilleurScore(),750, 52);
		buffer.drawString(gestion.getNiveau(), 630, 330);
		buffer.drawString(gestion.getNbLignesSupprimees(), 630, 390);
		buffer.drawString("appuyez sur 'm' pour activer ou d�sactiver les sons", 500, 500);
		if(!jeu)
		{
			buffer.drawString("appuyez sur 'espace' pour lancer une nouvelle partie", 500, 520);
			buffer.setColor(Color.WHITE);
			buffer.drawString("Meilleurs Scores", 289, 235);
			for(int i=0; i<gestion.getGestionScore().getTabScore().length; i++)
			{
				buffer.drawString(""+gestion.getGestionScore().getTabScore()[i], 317, 260+(25*i));
			}
			buffer.setColor(Color.BLACK);
		}
        g.drawImage(image, 0, 0, this);
       

        
        
	}
	
	/**vide le buffer et met � jour l'affichage selon la matrice*/
	public void update(Graphics g)
	{
		buffer.drawImage(image,0,0,this);
//		buffer.fillRect(coinHautGauche.x,coinHautGauche.y,10*longueurCoteCarre,20*longueurCoteCarre);
//		buffer.clipRect(coinHautGauche.x,coinHautGauche.y,10*longueurCoteCarre,20*longueurCoteCarre);
		buffer.fillRect(0,0,800,600);
		buffer.clipRect(0,0,800,600);
		if(!pause)
		{	
			gestionSprites.colorisationPuit(gestion.getTab());
			gestionSprites.colorisationSuivant(gestion.getPieceSuivante());
		}
		else
		{
			gestionSprites.colorisationPuit(gestion.tabPause());
			gestionSprites.colorisationSuivant(gestion.pieceSuivantePause());
		}
		if(!jeu)
		{
			gestionSprites.colorisationSuivant(gestion.pieceSuivantePause());
		}
	
		
		paint(g);
		
	}
	
	/**boucle d'animation*/
	@Override
	public void run() 
	{
		while(true)
		{
			try 
				{Thread.sleep(50);} 
			catch (InterruptedException e) {}
			if(!pause && jeu)
			{
				if(chrono==0)
					{chrono=System.nanoTime();}
				else
				{ 
					if(System.nanoTime()>=chrono+(400000000/(1+(this.gestion.getGestionScore().getNiveau())/2)))
					{
						gestion.update();
						chrono=System.nanoTime();
						if(gestion.isPerdu()){//si le joueur a perdu
							jeu = false; //on indique que la partie et termin�
		            		gestionSprites.setGameOverVisible(true);

						}
					}
				}
			}
			this.repaint();	
		}
		
	} 
	
	/**arr�t de l'animation*/
	public void stop() 
	{
		if (animation != null) 
		{
			animation.interrupt(); 
			animation = null;
		}
	}

	/**inner class pour la gestion des touches*/	
	private class EvenementClavier extends KeyAdapter{
	@Override
		public void keyPressed(KeyEvent e) 
		{
			int touche = e.getKeyCode();
			if (touche == KeyEvent.VK_SPACE) //d�but de partie
			{
            	if(!pause && !jeu)
            	{
            		jeu = true;
            		gestionSprites.setGameOverVisible(false);
            		gestion.init();
            		return;
            	}
			}
			
            if (touche == KeyEvent.VK_ESCAPE){ //pause
            	if(!pause && jeu && !gestion.isPerdu())
            	{
            		pause = true;
            		gestionSprites.setPauseVisible(true);
            		gestion.stopMusique();   // on arrete la musique lors d'une pause
            		return;
            	}
            	
            	if(pause && jeu && !gestion.isPerdu())
            	{
            		pause = false;
            		gestionSprites.setPauseVisible(false);
            		gestion.jouerMusique();   // on recommence la musique une fois la pause finie
            		return;
            	}
        	}
		
			if(jeu && !pause)
			{
				if(touche == KeyEvent.VK_SPACE || touche == KeyEvent.VK_W) //tourne la pi�ce actuelle
				{
					gestion.tourne();
				    repaint();
				}
				
				if(touche == KeyEvent.VK_CONTROL || touche == KeyEvent.VK_X)//tourne la pi�ce actuelle dans le sens inverse
				{
					gestion.tourneInverse();
				    repaint();
				}
				
				switch (touche) 
				{
					case KeyEvent.VK_LEFT:	//bouge la pi�ce � gauche
						gestion.aGauche();
						repaint();
						break;
					
					case KeyEvent.VK_RIGHT:	//bouge la pi�ve � droite
						gestion.aDroite();
						repaint();
						break;

					case KeyEvent.VK_DOWN:	//fait tomber d'un cran la pi�ce
						if(gestion.getAPuDescendre())
						{
							gestion.enBas();
							repaint();
						}
						break;
					
					case KeyEvent.VK_UP:	//fait tomber la pi�ce au plus bas
						if(gestion.getAPuDescendre())
						{
							while(gestion.enBas());
						}
						repaint();	   
				}
				
				if(touche == KeyEvent.VK_M)	//active ou d�sactive les sons
				{
					gestion.toogleSound();
					gestion.toogleMusique();
				}
			}
		}
	}
}
